using System;
using System.Text;
using System.Collections;
using System.Reflection;

namespace Zeus.DotNetScript
{
	/// <summary>
	/// Summary description for DotNetScriptEngine.
	/// </summary>
	public class DotNetScriptEngine : IZeusScriptingEngine
	{
		protected DotNetScriptCodeParser _dotNetScriptCodeParser = null;
		protected DotNetScriptExecutioner _dotNetScriptExecutioner = null;

		internal const string DLLREF = "DLLREF";
		internal const string USE_NAMESPACE = "USE";

		protected string[] _supportedLanguages = new string[] 
			   { 
				   ZeusConstants.Languages.JSCRIPTNET, 
				   ZeusConstants.Languages.JSHARP, 
				   ZeusConstants.Languages.CSHARP, 
				   ZeusConstants.Languages.VBNET 
			   };

		public DotNetScriptEngine() {}

		public string EngineName
		{
			get { return ZeusConstants.Engines.DOT_NET_SCRIPT; }
		}

		public IZeusCodeParser CodeParser
		{
			get 
			{
				if (_dotNetScriptCodeParser == null) 
				{
					_dotNetScriptCodeParser = new DotNetScriptCodeParser(this);
				}
				return _dotNetScriptCodeParser;
			}
		}

		public IZeusExecutioner Executioner
		{
			get 
			{
				if (_dotNetScriptExecutioner == null) 
				{
					_dotNetScriptExecutioner = new DotNetScriptExecutioner(this);
				}
				return _dotNetScriptExecutioner;
			}
		}

		public string[] SupportedLanguages
		{
			get { return _supportedLanguages; }
		}

		public bool IsSupportedLanguage(string language) 
		{
			foreach (string lang in _supportedLanguages) 
			{
				if (lang == language) return true;
			}
			return false;
		}

		public bool Execute(ZeusInput input, ZeusOutput output, string code)
		{
			return false;
		}

		#region Build extending Referece list classes
		
		internal ArrayList BuildDLLNames() 
		{
			ArrayList list = new ArrayList();

			foreach (ZeusScriptableObject scriptingObj in ZeusFactory.ScriptableObjects)
			{
				if (scriptingObj.DllReference != null)
				{
					if(!list.Contains(scriptingObj.DllReference)) 
						list.Add(scriptingObj.DllReference);
				}
			}

			return list;
		}
		
		internal string BuildImportStatments(string language, ArrayList references) 
		{
			StringBuilder builder = new StringBuilder();

			foreach (string ns in references)
			{
				if (language == ZeusConstants.Languages.CSHARP) 
				{
					builder.Append("using ");
					builder.Append(ns);
					builder.Append(";\r\n");
				}
				else if (language == ZeusConstants.Languages.VBNET) 
				{
					builder.Append("Imports ");
					builder.Append(ns);
					builder.Append("\r\n");
				}
			}

			return builder.ToString();
		}

		internal string BuildGuiClass(string language) 
		{		
			StringBuilder builder = new StringBuilder();

			if (language == ZeusConstants.Languages.CSHARP) 
			{
				builder.Append("//-- Class DotNetScriptGui Generated by Zeus\r\n");
				builder.Append("namespace Zeus.DotNetScript\r\n");
				builder.Append("{\r\n");
				builder.Append("\tpublic abstract class DotNetScriptGui : _DotNetScriptGui\r\n");
				builder.Append("\t{\r\n");

				foreach (ZeusScriptableObject scriptingObj in ZeusFactory.ScriptableObjects)
				{
					builder.Append("\t\tprotected ");
					builder.Append(scriptingObj.ClassPath);
					builder.Append(" ");
					builder.Append(scriptingObj.VariableName);
					builder.Append(";\r\n");
				}

				builder.Append("\t\tpublic DotNetScriptGui(ZeusGuiContext context) : base(context)\r\n");
				builder.Append("\t\t{\r\n");;
			
				foreach (ZeusScriptableObject scriptingObj in ZeusFactory.ScriptableObjects)
				{
					builder.Append("\t\t\tthis.");
					builder.Append(scriptingObj.VariableName);
					builder.Append(" = context.Objects[\"");
					builder.Append(scriptingObj.VariableName);
					builder.Append("\"] as ");
					builder.Append(scriptingObj.ClassPath);
					builder.Append(";\r\n");
				}
		
				builder.Append("\t\t}\r\n\t}\r\n}\r\n");
			}
			else if (language == ZeusConstants.Languages.VBNET) 
			{
				builder.Append("'-- Class DotNetScriptGui Generated by Zeus\r\n");
				builder.Append("Public MustInherit Class DotNetScriptGui\r\n");
				builder.Append("\t\tInherits _DotNetScriptGui\r\n");

				foreach (ZeusScriptableObject scriptingObj in ZeusFactory.ScriptableObjects)
				{
					builder.Append("\tProtected ");
					builder.Append(scriptingObj.VariableName);
					builder.Append(" As ");
					builder.Append(scriptingObj.ClassPath);
					builder.Append("\r\n");
				}

				builder.Append("\tPublic Sub New(context As ZeusGuiContext)\r\n");
				builder.Append("\t\tMyBase.New(context)\r\n");

				foreach (ZeusScriptableObject scriptingObj in ZeusFactory.ScriptableObjects)
				{
					builder.Append("\t\tMe.");
					builder.Append(scriptingObj.VariableName);
					builder.Append(" = CType(context.Objects.Item(\"");
					builder.Append(scriptingObj.VariableName);
					builder.Append("\"), ");
					builder.Append(scriptingObj.ClassPath);
					builder.Append(")\r\n");
				}
		
				builder.Append("\tEnd Sub\r\nEnd Class\r\n");
			}
			
			return builder.ToString();
		}

		internal string BuildBodyClass(string language) 
		{		
			StringBuilder builder = new StringBuilder();

			if (language == ZeusConstants.Languages.CSHARP)
			{
				builder.Append("//-- Class DotNetScriptTemplate Generated by Zeus\r\n");
				builder.Append("namespace Zeus.DotNetScript\r\n");
				builder.Append("{\r\n");
				builder.Append("\tpublic abstract class DotNetScriptTemplate : _DotNetScriptTemplate\r\n");
				builder.Append("\t{\r\n");

				foreach (ZeusScriptableObject scriptingObj in ZeusFactory.ScriptableObjects)
				{
					builder.Append("\t\tprotected ");
					builder.Append(scriptingObj.ClassPath);
					builder.Append(" ");
					builder.Append(scriptingObj.VariableName);
					builder.Append(";\r\n");
				}		

				builder.Append("\t\tpublic DotNetScriptTemplate(ZeusTemplateContext context) : base(context)\r\n");
				builder.Append("\t\t{\r\n");

				foreach (ZeusScriptableObject scriptingObj in ZeusFactory.ScriptableObjects)
				{
					builder.Append("\t\t\tthis.");
					builder.Append(scriptingObj.VariableName);
					builder.Append(" = context.Objects[\"");
					builder.Append(scriptingObj.VariableName);
					builder.Append("\"] as ");
					builder.Append(scriptingObj.ClassPath);
					builder.Append(";\r\n");
				}
			
				builder.Append("\t\t}\r\n\t}\r\n}\r\n");
			}
			else if (language == ZeusConstants.Languages.VBNET) 
			{
				builder.Append("'-- Class DotNetScriptTemplate Generated by Zeus\r\n");
				builder.Append("Public MustInherit Class DotNetScriptTemplate\r\n");
				builder.Append("\t\tInherits _DotNetScriptTemplate\r\n");

				foreach (ZeusScriptableObject scriptingObj in ZeusFactory.ScriptableObjects)
				{
					builder.Append("\tProtected ");
					builder.Append(scriptingObj.VariableName);
					builder.Append(" As ");
					builder.Append(scriptingObj.ClassPath);
					builder.Append("\r\n");
				}

				builder.Append("\tPublic Sub New(context As ZeusTemplateContext)\r\n");
				builder.Append("\t\tMyBase.New(context)\r\n");

				foreach (ZeusScriptableObject scriptingObj in ZeusFactory.ScriptableObjects)
				{
					builder.Append("\t\tMe.");
					builder.Append(scriptingObj.VariableName);
					builder.Append(" = CType(context.Objects.Item(\"");
					builder.Append(scriptingObj.VariableName);
					builder.Append("\"), ");
					builder.Append(scriptingObj.ClassPath);
					builder.Append(")\r\n");
				}
		
				builder.Append("\tEnd Sub\r\nEnd Class\r\n");
			}

			return builder.ToString();
		}
		#endregion

		#region Default text for a new template
		public string GetNewTemplateText(string language)
		{
			StringBuilder builder = new StringBuilder();

			if (language == ZeusConstants.Languages.VBNET)
			{
				//Set the Body Text
				builder.Append("<%\r\n");
				builder.Append("Public Class GeneratedTemplate\r\n");
				builder.Append("\t\t\tInherits DotNetScriptTemplate\r\n");
				builder.Append("\r\n");
				builder.Append("\tPublic Sub New(context As ZeusTemplateContext)\r\n");
				builder.Append("\t\tMyBase.New(context)\r\n");
				builder.Append("\tEnd Sub\r\n");
				builder.Append("\r\n");
				builder.Append("\tPublic Overrides Sub Render\r\n");
				builder.Append("%>\r\n");
				builder.Append("Literal content goes here.\r\n");
				builder.Append("<%\r\n");
				builder.Append("\tEnd Sub\r\n");
				builder.Append("\r\n");
				builder.Append("End Class\r\n");
				builder.Append("%>");
			}
			else if (language == ZeusConstants.Languages.CSHARP)
			{
				//Set the Body Text
				builder.Append("<%\r\n");
				builder.Append("public class GeneratedTemplate : DotNetScriptTemplate\r\n");
				builder.Append("{\r\n");
				builder.Append("\tpublic GeneratedTemplate(ZeusTemplateContext context) : base(context) {}\r\n");
				builder.Append("\r\n");
				builder.Append("\tpublic override void Render()\r\n");
				builder.Append("\t{\r\n");
				builder.Append("%>\r\n");
				builder.Append("Literal content goes here.\r\n");
				builder.Append("<%\r\n");
				builder.Append("\t}\r\n");
				builder.Append("\r\n");
				builder.Append("}\r\n");
				builder.Append("%>");
			}

			return builder.ToString();
		}

		public string GetNewGuiText(string language)
		{
			StringBuilder builder = new StringBuilder();

			if (language == ZeusConstants.Languages.VBNET)
			{
				//Set the Interface Text
				builder.Append("\r\n");
				builder.Append("Public Class GeneratedGui\r\n");
				builder.Append("\t\t\tInherits DotNetScriptGui\r\n");
				builder.Append("\r\n");
				builder.Append("\tPublic Sub New(context As ZeusGuiContext)\r\n");
				builder.Append("\t\tMyBase.New(context)\r\n");
				builder.Append("\tEnd Sub\r\n");
				builder.Append("\r\n");
				builder.Append("\tPublic Overrides Sub Setup\r\n");
				builder.Append("\tEnd Sub\r\n");
				builder.Append("\r\n");
				builder.Append("End Class");
			}
			else if (language == ZeusConstants.Languages.CSHARP)
			{
				//Set the Interface Text
				builder.Append("\r\n");
				builder.Append("public class GeneratedGui : DotNetScriptGui\r\n");
				builder.Append("{\r\n");
				builder.Append("\tpublic GeneratedGui(ZeusGuiContext context) : base(context) {}\r\n");
				builder.Append("\r\n");
				builder.Append("\tpublic override void Setup()\r\n");
				builder.Append("\t{\r\n");
				builder.Append("\t}\r\n");
				builder.Append("\r\n");
				builder.Append("}");
			}

			return builder.ToString();
		}
		#endregion
	}
}
